package org.example.admin.service.impl;

import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.example.admin.bo.MenuBO;
import org.example.admin.constant.CustomConstants;
import org.example.admin.dao.MenuDao;
import org.example.admin.dto.MenuDto;
import org.example.admin.entity.MenuEntity;
import org.example.admin.service.RoleMenuService;
import org.example.admin.vo.*;
import org.example.core.constant.TokenConstants;
import org.example.core.utils.PageUtils;
import org.example.core.utils.R;
import org.example.security.handler.SecurityHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.example.admin.service.MenuService;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


@Service("menuService")
public class MenuServiceImpl implements MenuService {

    @Autowired
    private MenuDao menuDao;
    @Autowired
    private RoleMenuService roleMenuService;

    // 菜单展示列表
    @Override
    public PageUtils list(MenuDto menuDto) {
        if (menuDto.needLimit()){
            PageHelper.startPage(menuDto.getPage(), menuDto.getPageSize());
        }
        List<MenuVo> vos = menuDao.list(menuDto);
        return new PageUtils(new PageInfo<>(vos));
    }

    // 查询单个菜单信息
    @Override
    public MenuVo detail(Long id) {
        return menuDao.detail(id);
    }

    // 保存菜单
    @Override
    public int save(MenuBO menu) {
        Long userId = Long.parseLong(SecurityHandler.getData().get(TokenConstants.USER_ID));
        menu.setCreateUser(userId);
        menu.setUpdateUser(userId);
        return menuDao.save(menu);
    }

    // 修改单个菜单
    @Override
    public int update(MenuBO menu) {
        Long userId = Long.parseLong(SecurityHandler.getData().get(TokenConstants.USER_ID));
        menu.setUpdateUser(userId);
        return menuDao.update(menu);
    }

    // 获取路由菜单
    @Override
    public List<MenuVo> routerList() {
        // 判断是否为超级管理员
        Long userId = Long.parseLong(SecurityHandler.getData().get(TokenConstants.USER_ID));
        List<MenuVo> menuEntities;
        if (userId == 1L){
            // 获取全部菜单
            menuEntities = menuDao.routerAll();
        }else {
            // 根据用户id查询菜单
            menuEntities = menuDao.routerByUserId(userId);
        }
        return topMenu(menuEntities);
    }

    // 获取用户权限
    @Override
    public Set<String> userPermissions(UserVo userVo) {
        if (userVo.getId() == 1L){
            Set<String> permissions = new HashSet<>();
            permissions.add("*:*:*");
            return permissions;
        }else {
            List<String> permissionsList = menuDao.permissionByUserId(userVo.getId());
            if (permissionsList != null){
                return permissionsList.stream().map(String::trim).collect(Collectors.toSet());
            }
            return null;
        }
    }

    @Override
    public List<MenuVo> tree() {
        List<MenuVo> menuVos = menuDao.menuAll();
        return topMenu(menuVos);
    }

    @Override
    @Transactional
    public R<?> delete(List<Long> ids) {
        Integer count = menuDao.countChildren(ids);
        if (count > 0){
            return R.error("存在子菜单不能删除");
        }
        // 删除角色权限
        roleMenuService.deleteByMenuId(ids);
        int delete = menuDao.detete(ids);
        if (delete > 0){
            return R.ok();
        }
        return R.error();
    }

    // 获取一级菜单
    private List<MenuVo> topMenu(List<MenuVo> menuVos){
        List<MenuVo> collect = menuVos.stream().filter(menuVo -> "0".equals(menuVo.getPid().toString()))
                .peek(menuVo -> menuVo.setChildren(getChildren(menuVo.getId(), menuVos))).collect(Collectors.toList());
        return collect;
    }

    // 根据一级菜单递归找子菜单
    private List<MenuVo> getChildren(Long menuId,List<MenuVo> menuVos){
        List<MenuVo> collect = menuVos.stream().filter(menuVo -> menuId.toString().equals(menuVo.getPid().toString()))
                .peek(menuVo -> menuVo.setChildren(getChildren(menuVo.getId(), menuVos)))
                .collect(Collectors.toList());
        return collect;
    }

    // 构建路由菜单
    public List<RouterVo> buildRouterMenu(List<MenuVo> menuVos){
        List<RouterVo> routerVos = new LinkedList<>();
        for (MenuVo menu : menuVos){
            RouterVo router = new RouterVo();
            router.setHidden("1".equals(menu.getVisible().toString()));
            router.setName(routeName(menu));
            router.setPath(path(menu));
            router.setComponent(getComponent(menu));
            router.setMeta(new MetaVo(menu.getName(), menu.getIcon()));

            List<MenuVo> menuChild = menu.getChildren();
            if (!menuChild.isEmpty() && CustomConstants.TYPE_M.equals(menu.getType())) {
                router.setRedirect("noRedirect");
                router.setChildren(buildRouterMenu(menuChild));
            }
            else if (menuOneC(menu)){
                router.setMeta(null);
                List<RouterVo> childrenList = new ArrayList<>();
                RouterVo children = new RouterVo();
                children.setPath(menu.getPath());
                children.setComponent(menu.getComponent());
                children.setName(StrUtil.upperFirst(menu.getPath()));
                children.setMeta(new MetaVo(menu.getName(), menu.getIcon()));
                childrenList.add(children);
                router.setChildren(childrenList);
            }
            routerVos.add(router);
        }
        return routerVos;
    }

    // 获取对应组件的方法
    private String getComponent(MenuVo menuVo){
        if (StrUtil.isNotEmpty(menuVo.getComponent()) && !menuOneC(menuVo)){
            return menuVo.getComponent();
        }
        else if (StrUtil.isEmpty(menuVo.getComponent()) && isNestView(menuVo)) {
            return CustomConstants.NEST_VIEW;
        }
        return CustomConstants.LAYOUT;

    }

    // 多级目录的组件判断
    private boolean isNestView(MenuVo menuVo){
        return CustomConstants.TYPE_M.equals(menuVo.getType()) && menuVo.getPid().intValue() != 0;
    }

    // 一级目录的Path和嵌套的不一样
    private String path(MenuVo menuVo){
        // 一级目录(类型为目录)
        if (menuVo.getPid().intValue() == 0 && StrUtil.isNotEmpty(menuVo.getPath()) && CustomConstants.TYPE_M.equals(menuVo.getType())) {
            return "/" + menuVo.getPath();
        }
        else if(menuOneC(menuVo)){
            // 一级目录(类型为菜单)
            return "/";
        }
        // 非一级目录
        return menuVo.getPath();
    }

    // 判断是否为一级菜单
    private boolean menuOneC(MenuVo menuVo) {
        return menuVo.getPid().intValue() == 0 && CustomConstants.TYPE_C.equals(menuVo.getType());
    }

    // 获取名称
    public String routeName(MenuVo menuVo) {
        // 一级目录（类型为菜单）
        if (menuOneC(menuVo)) {
            return "";
        }
        return StrUtil.upperFirst(menuVo.getPath());
    }
}